package org.spider.utils;

import cn.hutool.setting.dialect.Props;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.querys.MySqlQuery;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.fill.Column;
import com.baomidou.mybatisplus.generator.fill.Property;
import com.baomidou.mybatisplus.generator.keywords.MySqlKeyWordsHandler;

import java.util.*;

public class MybatisPlusGenerator {

    public static void main(String[] args) {
        FastAutoGenerator.create(dataSourceConfig())
                .globalConfig(MybatisPlusGenerator::globalConfig)
                .packageConfig(MybatisPlusGenerator::packageConfig)
//                .injectionConfig(consumer -> {
//                    Map<String, String> customFile = new HashMap<>();
//                    // DTO
//                    customFile.put("DTO.java", "/templates/entityDTO.java.ftl");
//                    consumer.customFile(customFile);
//                })
                .strategyConfig((scanner, builder) ->
                        strategyConfig(strategyConfig(getTables(scanner.apply("请输入表名；多个表用英文逗号分隔；所有输入 all：")), builder).build(), builder))
                .execute();
    }

    private static DataSourceConfig.Builder dataSourceConfig() {
        return new DataSourceConfig.Builder(
                Props.getProp("application.properties").getProperty("sql.datasource.url"),
                Props.getProp("application.properties").getProperty("sql.datasource.username"),
                Props.getProp("application.properties").getProperty("sql.datasource.password"))
                .dbQuery(new MySqlQuery())
                .schema("mybatis-plus")
                .typeConvert(new MySqlTypeConvert())
                .keyWordsHandler(new MySqlKeyWordsHandler());
    }

    private static void globalConfig(GlobalConfig.Builder builder) {
        String projectPath = System.getProperty("user.dir");
        builder.outputDir(projectPath + "/spider-web/spider-code-generator/src/main/java")
                .disableOpenDir() //禁止打开输出目录
                .author("lzy")
                .fileOverride() // 覆盖已生成文件
                .enableSwagger()
                .dateType(DateType.TIME_PACK)
                .commentDate("yyyy-MM-dd HH:mm:ss");
    }

    private static void packageConfig(PackageConfig.Builder builder) {
        String projectPath = System.getProperty("user.dir");
                builder.parent(Props.getProp("application.properties").getProperty("base.package.name"))
                .moduleName(Props.getProp("application.properties").getProperty("base.model.name")) // 设置父包模块名
                .entity("model.entity") //设置entity包名
                .other("model.dto") // 设置dto包名
                .pathInfo(Collections.singletonMap(OutputFile.xml, projectPath + "/spider-web/spider-code-generator/src/main/resources/mapper")) // 设置mapperXml生成路径
                .build();
    }

    private static TemplateConfig templateConfig() {
        /*
            模板引擎配置，默认 Velocity 可选模板引擎 Beetl 或 Freemarker
           .templateEngine(new BeetlTemplateEngine())
           .templateEngine(new FreemarkerTemplateEngine())
         */
        return new TemplateConfig.Builder()
                .disable(TemplateType.ENTITY)
                .entity("/templates/entity.java")
                .service("/templates/service.java")
                .serviceImpl("/templates/serviceImpl.java")
                .mapper("/templates/mapper.java")
                .xml("/templates/mapper.xml")
                .controller("/templates/controller.java")
                .build();
    }

    private static InjectionConfig injectionConfig() {
        InjectionConfig injectionConfig = new InjectionConfig();
        return new InjectionConfig.Builder()
                .beforeOutputFile((tableInfo, objectMap) -> {
                    System.out.println("tableInfo: " + tableInfo.getEntityName() + " objectMap: " + objectMap.size());
                })

                .customMap(Collections.singletonMap("test", "baomidou"))
                .customFile(Collections.singletonMap("test.txt", "/templates/test.vm"))
                .build();
    }

    private static StrategyConfig.Builder strategyConfig(List<String> list, StrategyConfig.Builder builder) {
        return builder.addInclude(list);
    }

    private static void strategyConfig(StrategyConfig strategyConfig, StrategyConfig.Builder builder) {
        builder.entityBuilder()
                .disableSerialVersionUID()
                .enableChainModel()
                .enableLombok()
                .enableRemoveIsPrefix()
                .enableTableFieldAnnotation()
                .enableActiveRecord()
                .naming(NamingStrategy.underline_to_camel)
                .columnNaming(NamingStrategy.underline_to_camel)
//                .addSuperEntityColumns("id", "created_time", "updated_time")
                .addTableFills(new Column("create_time", FieldFill.INSERT))
                .addTableFills(new Property("updateTime", FieldFill.INSERT_UPDATE))    //基于模型属性填充
                .idType(IdType.ASSIGN_ID)
                .formatFileName("%sEntity").build()

                .controllerBuilder()
                .enableHyphenStyle()
                .enableRestStyle()
                .build()

                .serviceBuilder()
                .formatServiceFileName("%sService")
                .formatServiceImplFileName("%sServiceImp")
                .build()

                .mapperBuilder()
                .enableMapperAnnotation()
                .enableBaseResultMap()
                .enableBaseColumnList()
                .formatMapperFileName("%sMapper")
                .formatXmlFileName("%sMapper").build();
    }

    // 处理 all 情况
    protected static List<String> getTables(String tables) {
        return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
    }
}
